package com.tarena.lbs.business.dao.repository.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.business.dao.mapper.StoreChainMapper;
import com.tarena.lbs.business.dao.mapper.StoreMapper;
import com.tarena.lbs.business.dao.repository.StoreESRepository;
import com.tarena.lbs.business.dao.repository.StoreRepository;
import com.tarena.lbs.business.enums.BusinessResultEnum;
import com.tarena.lbs.business.pojo.po.StoreChainPO;
import com.tarena.lbs.business.pojo.po.StorePO;
import com.tarena.lbs.business.pojo.po.StoreSearchPO;
import com.tarena.lbs.business.pojo.query.AreaStoreQuery;
import com.tarena.lbs.business.pojo.query.StoreChainQuery;
import com.tarena.lbs.business.pojo.query.StoreQuery;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class StoreRepositoryImpl implements StoreRepository {
    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private StoreESRepository storeESRepository;

    @Autowired
    private StoreChainMapper storeChainMapper;

    @Override
    public PageInfo<StorePO> pageList(StoreQuery query) {
        QueryWrapper<StorePO> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(query.getStoreHeadPhone())){
            queryWrapper.like("store_head_phone", query.getStoreHeadPhone());
        }
        if (StringUtils.isNotBlank(query.getStoreName())){
            queryWrapper.like("store_name", query.getStoreName());
        }
        if (query.getStoreStatus() != null){
            queryWrapper.eq(
                     "store_status", query.getStoreStatus()
            );
        }
        if (query.getStoreAddress() != null && query.getStoreAddress().length > 0){
            for (int i = 0; i < query.getStoreAddress().length; i++) {
                if (i == 0) {
                    queryWrapper.eq(
                            "province_id", Integer.valueOf(query.getStoreAddress()[i])
                    );
                }if (i == 1) {
                    queryWrapper.eq(
                            "city_id", Integer.valueOf(query.getStoreAddress()[i])
                    );
                }if (i == 2) {
                    queryWrapper.eq(
                            "area_id", Integer.valueOf(query.getStoreAddress()[i])
                    );
                }
            }
        }
        queryWrapper.eq("business_id", query.getBusinessId());
        if (query.getStartingTime() != null){
            queryWrapper.between(
                     "update_time", query.getStartingTime(), query.getEndTime()
            );
        }
        PageHelper.startPage(query.getPageNo(),query.getPageSize());
        List<StorePO> list = storeMapper.selectList(queryWrapper);
        log.info("查询门店{}",list);
        return new PageInfo<>(list);
    }

    //新增门店
    @Override
    public void add(StorePO storePO) {
        log.info("添加门店{}",storePO);
        storeMapper.insert(storePO);
        //将门店信息转换为es需要的格式
        StoreSearchPO storeSearchPO = new StoreSearchPO();
        //拷贝
        BeanUtils.copyProperties(storePO,storeSearchPO);
        //设置经纬度
        GeoPoint geoPoint = new GeoPoint(Double.valueOf(storePO.getStoreLatitude()),
                Double.valueOf(storePO.getStoreLongitude()));
        //设置经纬度转化格式为字符串
        storeSearchPO.setLocation(geoPoint.toString());
        //添加到es中
        storeESRepository.save(storeSearchPO);
    }


    //通过城市id查询门店
    @Override
    public PageInfo<StorePO> getStoreByCity(AreaStoreQuery query) {
        log.info("查询城市{}下的门店",query);
        List<StorePO> list;
        QueryWrapper<StorePO> queryWrapper = new QueryWrapper<>();
        // 使用IN条件来筛选城市ID
        queryWrapper.in("city_id", query.getCityIdList());
        PageHelper.startPage(query.getPageNo(),query.getPageSize() );
        list = storeMapper.selectList(queryWrapper);
        return new PageInfo<>(list);
    }

    //通过id查询店铺
    @Override
    public List<StorePO> selectStoreById(Integer businessId) {
        QueryWrapper<StorePO> queryWrapper = new QueryWrapper<>();
        if (businessId != null) {
            queryWrapper.eq("business_id", businessId);
        }
        return storeMapper.selectList(queryWrapper);
    }

    //跟新商铺
    @Override
    public void update(StorePO storePO) {
        log.info("更新门店{}",storePO);
        // 根据ID更新商店信息
        storeMapper.updateById(storePO);
    }

    //查询附近门店
    @Override
    public List<StoreSearchPO> getNearStore(String latitude, String longitude, double v) {
        log.info("查询附近门店{}{}{}",latitude,longitude,v);
        //搜索条件
        SearchRequest searchRequest = new SearchRequest("lbs_store");

        //请求源
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //点
        GeoPoint geoPoint =
                new GeoPoint(Double.valueOf(latitude),Double.valueOf(longitude));
        //查询指定范围内的文档
        GeoDistanceQueryBuilder query = QueryBuilders.geoDistanceQuery("location");
        //设置查询条件,将点和距离及单位一起设置进去
        query.point(geoPoint).distance(v, DistanceUnit.KILOMETERS);
        //设置查询条件
        sourceBuilder.query(query);
        //设置源
        searchRequest.source(sourceBuilder);
        //执行查询
        SearchResponse response = null;
        try {
            //获取响应,发送请求
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if(response == null){
            SearchHit[] hits = response.getHits().getHits();
            //非空判断
            if (hits != null && hits.length > 0){
                return Arrays.stream(hits).map(hit->{
                           String json = hit.getSourceAsString();
                           log.info("查询结果{}",json);
                           return JSON.parseObject(json, StoreSearchPO.class);
                        }).collect(Collectors.toList());
            }
        }
        return null;
    }

    @Override
    public void delete(Integer id,Integer BusinessId) {
        log.info("删除店铺{}",id);
        QueryWrapper<StorePO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",id);
        queryWrapper.eq("business_id",BusinessId);
        storeMapper.delete(queryWrapper);
    }

    @Override
    public StorePO getStoreById(Integer id) {
        log.info("查询店铺{}",id);
        return storeMapper.selectById(id);
    }

//    @Override
//    public PageInfo<StoreChainPO> getChainList(StoreChainQuery storeChainQuery) {
//        log.info("店铺连锁入参{}",storeChainQuery);
//        PageHelper.startPage(storeChainQuery.getPageNo(),storeChainQuery.getPageSize());
//        List<StoreChainPO> list = storeChainMapper.selectList(null);
//        return new PageInfo<>(list);
//    }

    @Override
    public Boolean addStoreChain(StoreChainPO storeChainPO) {
        log.info("添加连锁店铺{}",storeChainPO);
        int num = storeChainMapper.insert(storeChainPO);
        return num > 0;
    }

    @Override
    public StoreChainPO selectStoreChainById(Integer id) throws BusinessException {
        log.info("连锁店铺门店{}",id);
        QueryWrapper<StoreChainPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("store_id",id);
        StoreChainPO storeChainPO = storeChainMapper.selectOne(queryWrapper);
        Asserts.isTrue(storeChainPO == null, BusinessResultEnum.STORE_CHAIN_NOT_EXIST);
        return storeChainPO;
    }

    @Override
    public void deleteStoreChainByStoreId(Integer id) {
        log.info("删除连锁店铺{}",id);
        QueryWrapper<StoreChainPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("store_id",id);
        storeChainMapper.delete(queryWrapper);
    }

    @Override
    public void updateChain(StoreChainPO storeChainPO) {
        log.info("更新店铺链接{}",storeChainPO);
        storeChainMapper.updateById(storeChainPO);
    }
}
